# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
"""
GAIA Docker App - Natural language interface for containerization.

This app provides:
- Natural language commands for Docker containerization
- Intelligent Dockerfile generation based on application analysis
- Docker image building and container management
"""

import asyncio
import logging
import sys
from dataclasses import dataclass
from typing import Any, Optional

from gaia.agents.docker.agent import DEFAULT_MODEL, DockerAgent

logger = logging.getLogger(__name__)


@dataclass
class TaskResult:
    """Result from a task execution."""

    success: bool
    action: str
    data: Any
    error: Optional[str] = None


class DockerApp:
    """
    Main application class for Docker containerization.
    Uses the DockerAgent for all operations.
    """

    def __init__(
        self,
        directory: str = ".",
        verbose: bool = False,
        debug: bool = False,
        model: str = None,
    ):
        """
        Initialize the Docker App.

        Args:
            directory: Directory to analyze/containerize
            verbose: Enable verbose output
            debug: Enable debug logging
            model: LLM model to use (optional)
        """
        self.directory = directory
        self.verbose = verbose
        self.debug = debug
        self.model = model or DEFAULT_MODEL

        # Create agent with debug settings
        self.agent = DockerAgent(
            model_id=self.model,
            debug_prompts=False,
            show_prompts=self.debug,
            show_stats=self.debug or self.verbose,
            silent_mode=False,  # Always show agent steps for compelling demos
            debug=self.debug,
        )

        # Configure logging based on debug flag
        if self.debug:
            logging.basicConfig(
                level=logging.DEBUG,
                format="[%(asctime)s] | %(levelname)s | %(name)s | %(filename)s:%(lineno)d | %(message)s",
            )
            logger.setLevel(logging.DEBUG)
        else:
            logging.basicConfig(level=logging.WARNING)
            logger.setLevel(logging.WARNING)

    async def execute_command(self, command: str) -> TaskResult:
        """
        Execute a natural language command.

        Args:
            command: Natural language command to execute

        Returns:
            TaskResult with execution outcome
        """
        try:
            logger.debug(f"Executing command: {command}")

            # Enhance command with directory context if not already mentioned
            if (
                self.directory
                and self.directory != "."
                and "directory" not in command.lower()
            ):
                command = f"{command} in directory {self.directory}"

            # Use the agent's process_query directly - single entry point
            result = self.agent.process_query(command)

            # Base agent returns: status ("success", "failed", "incomplete"), result, conversation, etc.
            return TaskResult(
                success=result.get("status") == "success",
                action="query",
                data=result,
                error=(
                    result.get("error_history", [""])[0]
                    if result.get("error_history")
                    else None
                ),
            )

        except Exception as e:
            logger.error(f"Command execution failed: {e}")
            return TaskResult(success=False, action="error", data={}, error=str(e))

    def _display_result(self, result: TaskResult):
        """Display result in a formatted way."""
        # Check if Dockerfile was actually generated by looking at conversation
        dockerfile_generated = False
        if result.data and isinstance(result.data, dict):
            conversation = result.data.get("conversation", [])
            for message in conversation:
                if message.get("role") == "system" and isinstance(
                    message.get("content"), dict
                ):
                    content = message["content"]
                    if (
                        content.get("status") == "success"
                        and "dockerfile_content" in content
                    ):
                        dockerfile_generated = True
                        break

        # If Dockerfile was generated, show success regardless of intermediate errors
        if dockerfile_generated or result.success:
            print("✅ Success!")
            if result.data and isinstance(result.data, dict):
                # Extract and display tool execution results from conversation
                self._extract_and_display_tool_results(result.data)

                # Show debug information if enabled
                if self.debug:
                    print(f"🔍 Steps taken: {result.data.get('steps_taken', 0)}")
                    print(
                        f"💬 Conversation length: {len(result.data.get('conversation', []))}"
                    )
        else:
            print(f"❌ Failed: {result.error}")

    def _extract_and_display_tool_results(self, result_data: dict[str, Any]):
        """Extract tool execution results from conversation history and display them."""
        conversation = result_data.get("conversation", [])
        tool_results_found = False

        # Look through conversation for tool execution results
        for message in conversation:
            if message.get("role") == "system" and isinstance(
                message.get("content"), dict
            ):
                content = message["content"]

                # Check for directory analysis results
                if "app_type" in content and content.get("status") != "error":
                    tool_results_found = True
                    app_type = content.get("app_type", "unknown")
                    path = content.get("path", "")
                    print(f"📁 Analyzed application at: {path}")
                    print(f"🔍 Detected type: {app_type}")
                    if content.get("entry_point"):
                        print(f"🚀 Entry point: {content['entry_point']}")
                    if content.get("dependencies"):
                        print(f"📦 Dependencies: {content['dependencies']}")
                    if content.get("port"):
                        print(f"🔌 Port: {content['port']}")

                # Check for Dockerfile save results
                elif content.get("status") == "success" and content.get(
                    "path", ""
                ).endswith("Dockerfile"):
                    tool_results_found = True
                    print(f"✅ Saved Dockerfile at: {content.get('path', 'N/A')}")

                    if content.get("next_steps"):
                        print("\n📋 Next Steps:")
                        for step in content["next_steps"]:
                            print(f"{step}")

                # Check for Docker build results
                elif content.get("status") == "success" and content.get("image"):
                    tool_results_found = True
                    print(f"✅ Built Docker image: {content.get('image', 'N/A')}")
                    print(f"📦 {content.get('message', '')}")

                # Check for container run results
                elif content.get("status") == "success" and content.get("container_id"):
                    tool_results_found = True
                    print(f"✅ Container started: {content.get('container_id', 'N/A')}")
                    if content.get("url"):
                        print(f"🌐 Access at: {content['url']}")
                    print(f"📦 {content.get('message', '')}")

                # Check for errors
                elif content.get("status") == "error":
                    tool_results_found = True
                    print(f"❌ Error: {content.get('error', 'Unknown error')}")

        # If no specific tool results found, show the generic result
        if not tool_results_found:
            final_result = result_data.get("result", "Task completed successfully")
            if final_result != "Task completed successfully":
                print(f"📋 {final_result}")
            else:
                print("📋 Task completed successfully")


async def main(cli_args=None):
    """Main entry point for the Docker app.

    Args:
        cli_args: Pre-parsed arguments from CLI, or None to parse from sys.argv
    """
    if cli_args is not None:
        # Use pre-parsed arguments from CLI
        args = cli_args
    else:
        # Parse arguments ourselves (for standalone usage)
        import argparse

        parser = argparse.ArgumentParser(
            description="GAIA Docker App - Containerization Assistant"
        )
        parser.add_argument("command", help="Natural language command to execute")
        parser.add_argument(
            "-d", "--directory", default=".", help="Directory to analyze/containerize"
        )
        parser.add_argument(
            "-v", "--verbose", action="store_true", help="Enable verbose output"
        )
        parser.add_argument("--debug", action="store_true", help="Enable debug logging")
        parser.add_argument("--model", help="LLM model to use")

        args = parser.parse_args()

    # Create app
    app = DockerApp(
        directory=args.directory,
        verbose=args.verbose,
        debug=args.debug,
        model=args.model,
    )

    # Execute command
    result = await app.execute_command(args.command)
    app._display_result(result)  # pylint: disable=protected-access

    return 0 if result.success else 1


if __name__ == "__main__":
    sys.exit(asyncio.run(main()))
